<?php
include_once(dirname(__FILE__).'/../config/UCConfMacro.php');

class UCLibUserSession
{
    const UC_USER_SESSION_TOKEN = '__uust';
    const UC_USER_SESSION_ACCOUNT = '__uusa';
    const UC_USER_SESSION_TIMESTAMP = '__uustm';
    const UC_USER_SESSION_PTACCOUNT = '__uuspt';

    const UC_USER_SESSION_TIMEOUT = 28800;

    const UC_USER_SESSION_KEY = 'JETjGChMsJxLA3Go';

    const SDO_LAST_LOGINED_COOKIE = 'SDOLastLogin';

    private $_isLogined = false;
    private $_loginedUserid = false;
    private $_sessionTime = false;
	private $_inited = false;
    private $_logined_url = false;

    private $_error;

    private $_included = false;

    function __construct($logined_url = false)
    {
        if( !$this->_included ) {
            include_once(dirname(__FILE__).'/../libraries/Utils/UCLibXtea.php');
            include_once(dirname(__FILE__).'/../libraries/UCFuncUtils.php');
            include_once(dirname(__FILE__).'/../models/user/UCModUserStatistics.php');
            include_once(dirname(__FILE__).'/UCFuncUtils.php');
            $this->_included = true;
        }

        $this->_logined_url = $logined_url;
        @session_start();
    }

    function __destruct()
    {
    }

    /**
    * 如果失败，则可用此函数获取失败信息
    * @return string
    */
    public function getLastError()
    {
        return $this->_error;
    }

    /**
    * @target 获取当前登录的用户id
    * @return false/integer
    */
    public function getLoginedUserid()
    {
		if( !$this->_inited )
			$this->_init();
        return $this->_loginedUserid;
    }

    /**
    * @target 获取当前登录的pt帐号
    * @return false/string
    */
    public function getLoginedPtid()
    {
        return $_SESSION[self::UC_USER_SESSION_PTACCOUNT];
    }

    public function getLoginedTime()
    {
        return $_SESSION[self::UC_USER_SESSION_TIMESTAMP];
    }

    /**
    * @target 验证当前用户是否登录
    *
    * @param boolean $auto_redirect 如果未登录，是否需要跳转
    * @param string $ticket
    * @return true/false/header('Location:xxx')s
    */
    function checkLogin($auto_redirect = false, $ticket = NULL)
    {
		if( !$this->_inited )
			$this->_init();
        if( $this->_isLogined == true )
            return true;

        if( !extension_loaded('openssl') ) {
            $this->_error = 'openssl needed.';
            return false;
        }

        $refer = urlencode('http://'.$_SERVER['HTTP_HOST']. preg_replace('/ticket\=[^\?\&\=]+\&?/', '', $_SERVER['REQUEST_URI']) );
        if( $this->_logined_url != false ){
            $refer = urlencode($this->_logined_url."?refer=".$refer);
        }                                                                      
        $login_url = "https://cas.sdo.com/cas/login?service=$refer"; 

        if( $auto_redirect ) {
            header('Location: '.$login_url);
        }
        return false;
    }

    /**
    * 退出登录
    * @param boolean $auto_redirect 如果跳转，则会到cas注销整个sdo，否则只注销uc的登录状态
    * @return void
    */
    function logout($auto_redirect = true)
    {
        $this->_unsetLogin();
        if($auto_redirect) {
            #header('Location: https://cas.sdo.com/cas/logout?url=http://www.sdo.com/LoginPT.asp?domain=t.sdo.com');
			header('Location: https://cas.sdo.com/cas/logout?url=' . UC_CONF_UC_DOMAIN.'/welcome');
		}
    }

    private function _unsetLogin()
    {
        $this->_isLogined = false;
        $this->_loginedUserid = false;

        unset($_SESSION[self::UC_USER_SESSION_TOKEN]);
        unset($_SESSION[self::UC_USER_SESSION_ACCOUNT]);
        unset($_SESSION[self::UC_USER_SESSION_TIMESTAMP]);
        unset($_SESSION[self::UC_USER_SESSION_PTACCOUNT]);
        $_SESSION = array();

        setcookie(self::UC_USER_SESSION_TOKEN, '', time() - 86400, '/', '.sdo.com');
        setcookie(self::UC_USER_SESSION_ACCOUNT, '', time() - 86400, '/', '.sdo.com');
        setcookie(self::UC_USER_SESSION_TIMESTAMP, '', time() - 86400, '/', '.sdo.com');
    }

    private function _setLogin($account, $tm = NULL)
    {
        $this->_isLogined = true;
        $this->_loginedUserid = $account;
        if( !$tm )
            $tm = time();

        $token = $this->_encrypt_encode($account, $tm, $this->_ptid);

        $_SESSION[self::UC_USER_SESSION_TOKEN] = urltrim_base64_encode($token);
        $_SESSION[self::UC_USER_SESSION_ACCOUNT] = $account;
        $_SESSION[self::UC_USER_SESSION_TIMESTAMP] = $tm;
        $_SESSION[self::UC_USER_SESSION_PTACCOUNT] = $this->_ptid;

        setcookie(self::UC_USER_SESSION_TOKEN, urltrim_base64_encode($token), 0, '/', '.sdo.com');
        setcookie(self::UC_USER_SESSION_ACCOUNT, $account, 0, '/', '.sdo.com');
        setcookie(self::UC_USER_SESSION_TIMESTAMP, $tm, 0, '/', '.sdo.com');
    }

    /**
    * @target 从CAS验证用户是否登录
    *
    * @param string $ticket 从认证跳转回来的URL GET参数，可不填
    * @return true/false
    */
    private function _checkFromCAS($ticket)
    {
        if( !extension_loaded('openssl') ) {
            $this->_error = 'openssl needed.';
            return false;
        }
        if( !$ticket && array_key_exists('ticket', $_GET) )
            $ticket = $_GET['ticket'];

        if( !$ticket )
        {
            $this->_error = 'No Ticket Specified.';
            return false;
        }                                                                                              
        $http_ret = get_http_data("https://cas.sdo.com/cas/validate?service=".UC_CONF_UC_DOMAIN."&ticket=$ticket&extend=true"); 
        if( !$http_ret )
        {
            $this->_error = "Validate@CAS failed.[$http_ret]";
            header('cas1: '. json_encode($http_ret));
            return false;
        }
        $sdo_info = explode("\n",$http_ret);
        if(!isset($sdo_info[2]) || $sdo_info[0] != 'yes')
        {
            $this->_error = "Validate@CAS failed.[$http_ret]";
            header('cas2: '. json_encode($http_ret));                                                                                          
            return false;
        }
        $this->_ptid = iconv("GBK", "UTF-8", $sdo_info[1]);
        return $sdo_info[2];
    }

    function _initFromEnv()
    {
        if( isset($_GET['ticket']) && strlen($_GET['ticket'])>1 )
        {
            $this->_unsetLogin();
            return false;
        }
        if( empty($_COOKIE[self::UC_USER_SESSION_TOKEN]) )
        {
            $this->_unsetLogin();
            $this->_error = 'Empty SESSION COOKIE';
            return false;
        }
		//如果COOKIE中有SESSION TOKEN

		if( $_COOKIE[self::UC_USER_SESSION_TOKEN] == $_SESSION[self::UC_USER_SESSION_TOKEN] )
		{//有登录cookie且登录cookie与session一致
			$this->_loginedUserid = $_SESSION[self::UC_USER_SESSION_ACCOUNT];
            $this->_isLogined = true;
			return true;
		}

		//对有登录cookie, 则尝试解码
		$decode_ret = $this->_encrypt_decode(urltrim_base64_decode($_COOKIE[self::UC_USER_SESSION_TOKEN]));
		if( $decode_ret === false )
		{ //解码失败, 则登录失败
			$this->_error = 'encrypt_decode error';
			$this->_unsetLogin();
			return false;
		}

		$token = $decode_ret[self::UC_USER_SESSION_TOKEN];
		$tm = $decode_ret[self::UC_USER_SESSION_TIMESTAMP];
        $this->_ptid = $decode_ret[self::UC_USER_SESSION_PTACCOUNT];
		$current_tm = time();
		if( ($current_tm - $tm) > self::UC_USER_SESSION_TIMEOUT )
		{//如果在社区超时，则直接返回失败
			$this->_error = 'session timeout';
			$this->_unsetLogin();
			return false;
		}
		//如果未超时，则说明登录
		//$_SESSION[self::UC_USER_SESSION_TOKEN] = $_COOKIE[self::UC_USER_SESSION_TOKEN];
        $this->_setLogin($decode_ret[self::UC_USER_SESSION_ACCOUNT], $decode_ret[self::UC_USER_SESSION_TIMESTAMP]);

		return true;
    }

	private function _init()
	{
		if( !$this->_inited )
	        $this->_initFromEnv();
        $ticket = '';
        if( array_key_exists('ticket', $_GET) )
            $ticket = $_GET['ticket'];
        if( !$this->_isLogined )
        {
            $account = $this->_checkFromCAS($ticket);
            if( $account !== false ) {
                $this->_setLogin($account);
                //登录时调接口更新统计信息字段
                UCModUserStatistics::getStat($this->_loginedUserid)->onUserLogin(get_client_ip());
            }
        }
		$this->_inited = true;
	}

    private function _encrypt_encode($account, $tm, $ptid)
    {
        $ar = array(
           self::UC_USER_SESSION_ACCOUNT => $account,
           self::UC_USER_SESSION_TIMESTAMP => $tm,
           self::UC_USER_SESSION_PTACCOUNT => $ptid
        );
        $serial_ar = serialize($ar);
        $xtea = new UCLibXtea();
        $ciphertext = $xtea->Encrypt($serial_ar, self::UC_USER_SESSION_KEY);
        return $ciphertext;
    }

    private function _encrypt_decode($ciphertext)
    {
        //解密
        $xtea = new UCLibXtea();
        $plain_text = $xtea->Decrypt($ciphertext, self::UC_USER_SESSION_KEY);
        if( !$plain_text )
            return false;
        $ar = unserialize($plain_text);
        $account = $ar[self::UC_USER_SESSION_ACCOUNT];
        $tm = $ar[self::UC_USER_SESSION_TIMESTAMP];
        $ptid = $ar[self::UC_USER_SESSION_PTACCOUNT];
        return $ar;
    }

    /**
    * 根据数字帐号获取pt帐号
    *
    * @param long $uid
    * @return false/string
    */
    private function _uid2ptid($uid)
    {
        $http_ret = get_http_data("http://ptcom.sdo.com/common/ConvertId.aspx?uuid=$uid");
        if( !$http_ret )
        {
            $this->_error = "Validate@CAS failed.[$http_ret]";
            return false;
        }
        $sdo_info = explode("^",$http_ret);
        if(!isset($sdo_info[2]) || $sdo_info[0] !== '0')
        {
            $this->_error = "get from ptcom failed.[$http_ret]";
            return false;
        }
        return $sdo_info[2];
    }
}
/**
//echo "init...\n";
error_reporting(E_ALL);
$user = new UserSession();
$ret = $user->checkLogin(true);
if( !$ret )
{
    //header('Location: '.$url);
    echo "not logined:".$user->getLastError();
    exit;
}

echo "logined: ". $user->getLoginedUserid();
*/
?>